package vn.sunnet.game.SinhTon.object;

import java.util.Random;

import vn.sunnet.game.SinhTon.global.Assets;
import vn.sunnet.game.SinhTon.global.Dimension;
import vn.sunnet.game.SinhTon.global.Setting;
import vn.sunnet.game.SinhTon.map.PositionAppear;

import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;

public class Zombie extends DynamicGameObject {
	private int state_Zombie; // 0 la run, 1 attack, 2 la die
	private int id;
	private int score; // diem
	private float hp; // máu
	private int damageSpeed; // toc do sat thuong
	// zombie ơ trang thai chay, tan cong, chet, xoa
	private boolean isRun, isAttack, isDie, isRemove;
	private Animation animationMove, animationAttack;
	// huong xuat hien zombie: 1 bên trái,3 bên phải là đi ngang và 2 là đi
	// thẳng

	private Animation animationDie;
	private int direct;
	Random random;
	private PositionAppear positionAppear;
	private Rectangle bound; // bound de bat xet va cham giua dan va zombie
	TextureRegion texture;
	// thoi gian cua animation va thoi gian ke
	// tu khi zombie chuyen sang trang thai chet
	private float stateTime, timeDie;
	private float W_ZOMBIE, H_ZOMBIE;

	public Zombie(int id) {
		super(-100, 0, Dimension.W_ZOMBIE, Dimension.H_ZOMBIE);
		bound = new Rectangle();
		random = new Random();
		direct = random.nextInt(3) + 1; // random 1 trong 3 vị trí xuất hiện của
										// Zombie trên màn hình
		stateTime = 0;
		positionAppear = new PositionAppear(Assets.map, direct);
		// Vị trí ban đầu của Zombie
		position.x = positionAppear.getVector().x;
		position.y = positionAppear.getVector().y;

		this.id = id;
		isRun = true;
		initZombie();
		if (Setting.getBoolean(Setting.SOUND))
			Assets.arrSoundZombie.get(MathUtils.random(0, 5)).play(1);
		// texture = new TextureRegion();
	}

	private void initZombie() {
		animationMove = Assets.getAnimation(direct, id);
		animationDie = Assets.getAnimationDie(id);

		if (id == 11) {
			W_ZOMBIE = 120;
			H_ZOMBIE = 120;
		} else if (id == 8 || id == 9) {
			W_ZOMBIE = 90;
			H_ZOMBIE = 90;
		} else {
			W_ZOMBIE = 55;
			H_ZOMBIE = 70;
		}
		switch (id) {
		case 1:
			score = 1;
			hp = 15;
			velocity.x = velocity.y = 25 + (Assets.map - 1);
			damageSpeed = 15;
			break;

		case 2:
			score = 2;
			hp = 15;
			velocity.x = velocity.y = 25 + (Assets.map - 1);
			damageSpeed = 15;
			break;
		case 3:
			score = 3;
			hp = 15;
			velocity.x = velocity.y = 25 + (Assets.map - 1);
			damageSpeed = 15;
			break;
		case 4:
			score = 4;
			hp = 20;
			velocity.x = velocity.y = 36 + 1.6f * (Assets.map - 1);
			damageSpeed = 25;
			break;
		case 5:
			score = 5;
			hp = 20;
			velocity.x = velocity.y = 36 + 1.6f * (Assets.map - 1);
			damageSpeed = 25;
			break;
		case 6:
			score = 6;
			hp = 20;
			velocity.x = velocity.y = 36 + 1.6f * (Assets.map - 1);
			damageSpeed = 25;
			break;
		case 7:
			score = 7;
			hp = 25;
			velocity.x = velocity.y = 36 + 1.6f * (Assets.map - 1);
			damageSpeed = 25;
			break;
		case 8:
			score = 8;
			hp = 35;
			velocity.x = velocity.y = 36 + 1.6f * (Assets.map - 1);
			damageSpeed = 35;
			break;
		case 9:
			score = 9;
			hp = 40;
			velocity.x = velocity.y = 30 + (Assets.map - 1);
			damageSpeed = 45;
			break;
		case 10:
			score = 10;
			hp = 60;
			velocity.x = velocity.y = 40 + 2 * (Assets.map - 1);
			damageSpeed = 55;
			break;
		case 11:
			score = 11;
			hp = 60;
			velocity.x = velocity.y = 30 + (Assets.map - 1);
			damageSpeed = 80;
			break;
		}
	}

	public TextureRegion getTexture() {
		if (state_Zombie == 0) {
			texture = animationMove.getKeyFrame(stateTime, true);
		} else if (state_Zombie == 1)
			texture = animationAttack.getKeyFrame(stateTime, true);
		else {
			texture = animationDie.getKeyFrame(timeDie, true);
		}
		return texture;
	}

	public int getId() {
		return id;
	}

	public int getScore() {
		return score;
	}

	public float getHp() {
		return hp;
	}

	public int getDamageSpeed() {
		return damageSpeed;
	}

	public boolean isAttack() {
		return isAttack;
	}

	public void setAttack(boolean isAttack) {
		this.isAttack = isAttack;
	}

	public boolean isRemove() {
		return isRemove;
	}

	public boolean isRun() {
		return isRun;
	}

	public boolean isDie() {
		return isDie;
	}

	public void setDie(boolean isDie) {
		this.isDie = isDie;
	}

	// Ham dung khi Zombie chet se bo bound bat va cham di
	public void resetBound() {
		bound.x = 0;
		bound.y = 0;
		bound.height = 0;
		bound.width = 0;
	}

	// Zombie di chuyen
	public void move(float time, int speed) {
		/*
		 * Xử lý trạng thái di chuyển của Zombie theo từng map Có 3 hướng ra
		 * Zombie: 1 và 3 là đi ngang, 2 là đi thẳng
		 */
		switch (Assets.map) {
		case 1:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					// if ((position.x > 156 && position.y > 267)
					// || (position.x > 363)) {
					// setDirect(2);
					// animationMove = Assets.getAnimation(2, id);
					// } else
					// position.x += time * velocity.x * speed;
					if (position.x > 160) {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed;
					} else
						position.x += time * velocity.x * speed;
					break;

				case 2:
					// if (position.y < 200 && (position.x < 333)) {
					// animationMove = Assets.getAnimation(1, id);
					// setDirect(1);
					// } else
					// position.y -= time * velocity.y * speed;
					if (position.y < 200) {
						animationMove = Assets.getAnimation(1, id);
						setDirect(1);
					} else
						position.y -= time * velocity.y * speed;
					break;
				case 3:
					// if ((position.x < 440)) {
					// setDirect(2);
					// animationMove = Assets.getAnimation(2, id);
					// } else
					// position.x -= time * velocity.x * speed;

					if ((position.x < 710)) {
						position.x -= time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 2;
					} else
						position.x -= time * velocity.x * speed;
					break;
				}
			}
			break;

		case 2:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.x > 140) {
						position.y -= time * velocity.y * speed;
						position.x += time * velocity.x * speed;
					} else {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 3;
					}
					break;

				case 2:
					position.y -= time * velocity.y * speed;
					position.x += time * velocity.x * speed / 6;
					break;
				case 3:
					if ((position.x > 570)) {
						position.x -= time * velocity.x * speed;
					} else {
						animationMove = Assets.getAnimation(2, id);
						position.y -= time * velocity.y * speed;
						position.x -= time * velocity.x * speed / 3f;
					}
					break;
				}
			}
			break;
		case 3:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.x > 340) {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					} else
						position.x += time * velocity.x * speed;
					break;

				case 2:
					position.x -= time * velocity.x * speed / 6;
					position.y -= time * velocity.y * speed;
					break;
				case 3:
					if ((position.x < 395)) {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					} else
						position.x -= time * velocity.x * speed;
					break;
				}
			}
			break;
		case 4:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.y < 160) {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 2.2f;
					} else {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed;
					}

					break;
				case 2:
					position.y -= time * velocity.y * speed;
					break;
				case 3:
					position.x -= time * velocity.x * speed;
					position.y -= time * velocity.y * speed / 2.5f;
					break;
				}
			}
			break;
		case 5:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					position.x += time * velocity.x * speed;
					position.y -= time * velocity.y * speed * 1.05f;
					break;
				case 2:
					if (position.y > 240) {
						position.y -= time * velocity.y * speed;
						position.x -= time * velocity.x * speed / 2.7f;
					} else {
						animationMove = Assets.getAnimation(1, id);
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed;
					}
					break;
				case 3:
					if (position.y > 350 || position.y < 180) {
						setDirect(3);
						animationMove = Assets.getAnimation(1, id);
						position.x -= time * velocity.x * speed;
						position.y -= time * velocity.y * speed;
					} else {
						animationMove = Assets.getAnimation(2, id);
						position.y -= time * velocity.y * speed;
					}
					break;
				}
			}
			break;
		case 6:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.x < 410)
						position.x += time * velocity.x * speed;
					else {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					}
					break;
				case 2:
					if (position.y > 350) {
						position.x += time * velocity.x * speed / 1.2f;
						position.y -= time * velocity.y * speed;
					} else {
						position.y -= time * velocity.y * speed;
					}
					break;
				case 3:
					if (position.x > 430) {
						position.x -= time * velocity.x * speed * 1.3f;
						position.y -= 1.3f * time * velocity.y * speed / 3;
					} else {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					}
					break;
				}
			}
			break;
		case 7:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.x < 370) {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 1.5f;
					} else {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					}
					break;
				case 2:
					if (position.y > 420) {
						position.y -= time * velocity.y * speed;
					} else if (position.x < 360) {
						animationMove = Assets.getAnimation(1, id);
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed;
					} else {
						animationMove = Assets.getAnimation(2, id);
						position.y -= time * velocity.y * speed;
					}
					break;
				case 3:
					if ((position.x < 420)) {
						setDirect(2);
					} else
						position.x -= time * velocity.x * speed;

					break;
				}
			}
			break;

		case 8:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					position.x += time * velocity.x * speed;
					position.y -= time * velocity.y * speed / 4f;
					break;
				case 2:
					position.y -= time * velocity.y * speed;
					break;
				case 3:
					if (position.x > 470) {
						position.x -= time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 3;
					} else {
						setDirect(2);
						animationMove = Assets.getAnimation(2, id);
					}
					break;
				}
			}
			break;
		case 9:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					position.x += time * velocity.x * speed;
					position.y -= time * velocity.y * speed / 3.8f;
					break;
				case 2:
					if (position.y > 350) {
						position.x -= time * velocity.x * speed / 5;
						position.y -= time * velocity.y * speed * 1.33f;
					} else if (position.y > 140) {
						position.x += time * velocity.x * speed / 2;
						position.y -= time * velocity.y * speed * 1.33f;
					} else {
						position.y -= time * velocity.y * speed;
					}
					break;
				case 3:
					position.x -= time * velocity.x * speed;
					position.y -= time * velocity.y * speed / 3.3f;
					break;
				}
			}
			break;
		case 10:
			if ((Assets.polygonLocot.contains(this.getBound().x,
					this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width / 2,
							this.getBound().y))
					|| (Assets.polygonLocot.contains(
							this.getBound().x + this.getBound().width,
							this.getBound().y))) {
				this.setAnimationAttack(Assets.getAnimation(this.getDirect(),
						this.getId()));
				this.setState_Zombie(1);
			} else {
				switch (direct) {
				case 1:
					if (position.x < 190) {
						position.x += time * velocity.x * speed;
					} else {
						position.x += time * velocity.x * speed;
						position.y -= time * velocity.y * speed / 2;
					}
					break;
				case 2:
					if (position.y > 200) {
						position.y -= time * velocity.y * speed * 1.33f;
					} else {
						animationMove = Assets.getAnimation(1, id);
						setDirect(1);
					}
					break;
				case 3:
					position.x -= time * velocity.x * speed / 2.3f;
					position.y -= time * velocity.y * speed;
					break;
				}
			}
			break;
		default:
			break;
		}
	}

	/**
	 * @param time
	 * @param speed
	 *            toc do di chuyen cua Zombie
	 */
	public void update(float time, int speed) {
		stateTime += 0.5f * time;
		// Tinh lai vi tri cua hinh vuong bound Zombie dung de bat va cham
		bounds.x = position.x - bounds.width / 2;
		bounds.y = position.y - bounds.height / 2;
		if (state_Zombie != 2) {
			// Cho bound nay nho de bat va cham cho chinh xac

			if (this.getId() < 8 || id == 10) {
				bound.x = (int) (bounds.x + 7);
				bound.y = (int) (bounds.y + 8);
				bound.width = (int) (W_ZOMBIE - 15);
				bound.height = (int) (H_ZOMBIE - 15);
			} else if (id == 9 || id == 8) {
				bound.x = (int) (bounds.x + 24);
				bound.y = (int) (bounds.y + 8);
				bound.width = (int) (W_ZOMBIE - 48);
				bound.height = (int) (H_ZOMBIE - 37);
			} else {
				bound.x = (int) (bounds.x + 16);
				bound.y = (int) (bounds.y + 10);
				bound.width = (int) (W_ZOMBIE - 40);
				bound.height = (int) (H_ZOMBIE - 25);
			}
		} else
			// neu ma o trang thai chet thi bo bound di
			this.resetBound(); // phai de ham resetBound tai day de khoi bat va
								// cham khi zombie da chet

		switch (state_Zombie) {
		case 0:
			// run
			this.move(time, speed);
			break;

		case 1:

			// attack
			break;
		case 2:
			timeDie += 0.5f * time;
			// Cho thoi gian chet cua Zombie laf 0.7
			if (timeDie > 0.7) {
				// Sau 0.7s tu luc chet thi se xoa zombie
				isRemove = true;
			}
			break;
		}
	}

	// Zombie bị bắn
	public void shot(int dame) {
		hp -= dame;
		// Neu ma het mau thi chuyen sang trang thai chet
		if (hp <= 0) {
			isDie = true;
			setState_Zombie(2);
		}
	}

	public int getDirect() {
		return direct;
	}

	public void setDirect(int direct) {
		this.direct = direct;
	}

	public Rectangle getBound() {
		return bound;
	}

	public int getState_Zombie() {
		return state_Zombie;
	}

	public void setState_Zombie(int state_Zombie) {
		this.state_Zombie = state_Zombie;
	}

	public float getTimeDie() {
		return timeDie;
	}

	public float getH_ZOMBIE() {
		return H_ZOMBIE;
	}

	public float getW_ZOMBIE() {
		return W_ZOMBIE;
	}

	public Animation getAnimationAttack() {
		return animationAttack;
	}

	public void setAnimationAttack(Animation a) {
		this.animationAttack = a;
	}

	public Animation getAnimati1() {
		return animationDie;
	}

	public void setAnimationDie(Animation a) {
		this.animationDie = a;
	}
}
